﻿using Bll;
using Bll.User;
using Infrastructure.Attributes.Ioc;
using Infrastructure.MyException;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using ShareCode.Dto;
using ShareCode.Entity;
using ShareCode.KeyValue;

namespace ApiApp.Controllers
{
    /// <summary>
    /// SerialNumber<100
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class BaseBaseController<T> : Controller, IBaseController<T> where T : BaseBaseEntity, new()
    {
        protected BaseBaseBll<T>? _Bll;

        protected virtual BaseBaseBll<T>? Bll { get { return _Bll; } }

        [Autowired]
        public UserAccountBll? AccountBll { get; set; }


        #region 返回配置
        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        protected JsonResult Okk<TT>(TT? data = default, string msg = "")
        {
            return new JsonResult(
                new ResultDto<TT>
                {
                    Code = (int)EnumResultCode.OK,
                    Data = data,
                    Message = msg
                });
        }

        protected async Task<JsonResult> OkkAsync<TT>(Task<TT>? data = null, string msg = "")
        {
            if (data == null)
            {
                return Err(new ShowUserLogicException(msg));
            }


            try
            {


                var DData = await data;

                return new JsonResult(new ResultDto<TT>
                {
                    Code = (int)EnumResultCode.OK,
                    Data = DData,
                    Message = msg
                });
            }
            catch (ShowUserLogicException ex)
            {
                return Err(ex);
            }
            catch (Exception ex)
            {
                return Err(new ShowUserLogicException(ex.Message));
            }

        }


        protected JsonResult Err(ShowUserLogicException? exception)
        {
            exception ??= new ShowUserLogicException("未知异常");

            var msg = string.IsNullOrWhiteSpace(exception.Message) ? "未知原因引起服务器端错误" : exception.Message;
            var re = new JsonResult(new ResultDto<Dictionary<string, List<string>>> { Code = (int)EnumResultCode.ServerErr, DetailMSg = exception.SonErrs, Message = msg });

            return re;
        }


        protected JsonResult ErrPermi<TT>(string msg = "", TT? data = default)
        {
            msg = string.IsNullOrWhiteSpace(msg) ? "服务器端错误" : msg;
            return new JsonResult(new ResultDto<TT> { Code = (int)EnumResultCode.ErrPermission, Data = data, Message = msg });
        }
        #endregion

        protected virtual bool Verify<TT>(TT param, out ShowUserLogicException? ex) where TT : class, new()
        {
            ex = null;
            return true;
        }

        #region  


        [HttpPost("Insert")]
        public async virtual Task<JsonResult> InsertAsync([FromBody] T entity)
        {
            if (!Verify(entity, out ShowUserLogicException? ex))
            {
                return Err(ex);
            }

            return await OkkAsync(Bll!.InsertAsync(entity));
        }
        [HttpPost("Updata")]
        public async virtual Task<JsonResult> UpdataAsync([FromBody] T entity)
        {
            if (!Verify(entity, out ShowUserLogicException? ex))
            {
                return Err(ex);
            }

            return await OkkAsync(Bll!.UpdateAsync(entity));
        }

        [HttpGet("GetEntity/{id}")]
        public async virtual Task<JsonResult> GetEntity(long Id)
        {
            return await OkkAsync(Bll!.GetEntityAsync(Id));
        }

        [HttpPost("UnLogicDelete/{id}")]
        public async virtual Task<JsonResult> UnLogicDelete(long Id)
        {
            return await OkkAsync(Bll!.UnLogicDeleteByIdAsync(Id));
        }

        [HttpPost("UnLogicDelete")]
        public async virtual Task<JsonResult> UnLogicDelete([FromBody] List<long> Ids)
        {
            return await OkkAsync(Bll!.UnLogicDeleteByIdAsync(Ids));
        }


        [HttpPost("LogicDelete/{id}")]
        public async virtual Task<JsonResult> LogicDelete(long Id)
        {
            return await OkkAsync(Bll!.LogicDeleteByIdAsync(Id));
        }

        [HttpPost("LogicDelete")]
        public async virtual Task<JsonResult> LogicDelete([FromBody] List<long> Ids)
        {
            return await OkkAsync(Bll!.LogicDeleteByIdAsync(Ids));
        }


        [HttpPost("UpdateState/{id}/{state}")]
        public async virtual Task<JsonResult> UpdateState(long Id, int state)
        {
            return await OkkAsync(Bll!.UpdateStateAsync(Id, state));
        }

        [HttpPost("UpdateState/{state}")]
        public async virtual Task<JsonResult> UpdateState([FromBody] List<long> Ids, int state)
        {
            return await OkkAsync(Bll!.UpdateStateAsync(Ids, state));
        }


        [HttpPost("Delete/{id}")]
        public async virtual Task<JsonResult> Delete(long Id)
        {
            return await OkkAsync(Bll!.DeleteByIdAsync(Id));
        }

        [HttpPost("Delete")]
        public async virtual Task<JsonResult> Delete([FromBody] List<long> Ids)
        {
            return await OkkAsync(Bll!.DeleteByIdAsync(Ids));
        }

        [HttpPost("ListPage")]
        public async virtual Task<JsonResult> ListPage([FromBody] PagingDto? dto = null)
        {
            return await OkkAsync(Bll!.ListPageAsync(dto));
        }
        [HttpPost("List")]
        public async virtual Task<JsonResult> List([FromBody] PagingDto? dto = null)
        {
            return await OkkAsync(Bll!.ListAsync(dto));
        }


        [HttpPost("ListPageNoDelete")]
        public async virtual Task<JsonResult> ListPageNoDelete([FromBody] PagingDto? dto = null)
        {

            return await OkkAsync(Bll!.ListPageNoDeleteAsync(dto));
        }
        [HttpPost("ListNoDelete")]
        public async virtual Task<JsonResult> ListNoDelete([FromBody] PagingDto? dto = null)
        {
            return await OkkAsync(Bll!.ListNoDeleteAsync(dto));
        }
        #endregion



        /// 
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            //filterContext.HttpContext.Items.Add(filterContext)
            base.OnActionExecuting(filterContext);
            //long userid = GetUserId();

            //if (userid == 0)
            //{
            //var skipAuthorize = filterContext.ActionDescriptor.FilterDescriptors.Where(a => a.Filter is AuthSkipAttribute).Any();

            //TODO:先跳过token验证 alter by may 20210913
            //skipAuthorize = true;
            //

            //if (skipAuthorize)
            //{
            //    return;
            //}

            return;
            /*
            string msg = "";
            var aa = filterContext.HttpContext.Request.Headers;

            if (!aa.TryGetValue("token", out StringValues token0))
            {
                msg = string.Format("没有传输token");
                filterContext.Result = ErrPermi<object>(msg, 0);
                filterContext.HttpContext.Response.StatusCode = (int)EnumResultCode.ErrPermission;
                return;
            }

            var token = token0.ToString();

            var lifeTime = ConfigurationManagerModel.ThreadSafeReadInt(ConstantDefine.SESSION_LIFE_TIME);
            TimeSpan ts = new TimeSpan(0, lifeTime, 0);

            UserSessionInfoModel UserInfo = default;

            //以下部分以后都可以放入redis
            if (RedisHelper.GetObject(RedisDbBusiness.Core).KeyExists(RedisKeyPrefix.Token + token))
            {
                //如果存在
                UserInfo = RedisHelper.GetObject(RedisDbBusiness.Core).StringGet<UserSessionInfoModel>(RedisKeyPrefix.Token + token, ts);
            }

            //redis中有也可能取不出来，
            if (UserInfo == default)
            {
                UserInfo = await AccountBll.LoginByToken(token);

                RedisHelper.GetObject(RedisDbBusiness.Core).StringSet<UserSessionInfoModel>(RedisKeyPrefix.Token + token, UserInfo, ts);
            }

            if (!filterContext.HttpContext.Items.ContainsKey(ConstantDefine.SESSION_KEY))
            {
                filterContext.HttpContext.Items.Add(ConstantDefine.SESSION_KEY, UserInfo ?? throw new ShowUserLogicException("鉴权失败"));
            }
            else
            {
                filterContext.HttpContext.Items[ConstantDefine.SESSION_KEY] = UserInfo ?? throw new ShowUserLogicException("鉴权失败");
            }

            return;
            */
        }



    }
}
